home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
vol7n11.arc
/
PP711.ARC
/
SCANTD.ASM
next >
Wrap
Assembly Source File
|
1988-02-29
|
11KB
|
352 lines
name scantd
title SCANTD.ASM --- time & date input conversion
page 55,132
;
;
; SCANTD.ASM --- Convert ASCII times and dates
; to binary in MS-DOS format.
;
; Copyright (c) 1988 Ziff Communications Co.
; PC Magazine * Ray Duncan
;
; This module contains two public routines:
;
;
; SCANTIME convert ASCII time to binary
;
; Call with: DS:SI = address of string
;
; Returns: Carry = Set if bad time
; or
; Carry = Clear if good time
; CH = hour
; CL = minute
; DH = second
; DL = hundredths
; DS:SI = address+1 of terminator
; other registers preserved
;
;
; SCANDATE convert ASCII date to binary
;
; Call with: DS:SI = address of string
;
; Returns: Carry = Set if bad date
; or
; Carry = Clear if good date
; CX = year (1980+)
; DH = month (1-12)
; DL = day (1-31)
; DS:SI = address+1 of terminator
; other registers preserved
;
DGROUP group _DATA
_DATA segment word public 'DATA'
n1 dw 0 ; first converted field
n2 dw 0 ; second converted field
n3 dw 0 ; third converted field
dlmtab db '/-.' ; valid date delimiters
dlmtab_len equ $-dlmtab ; length of table
tlmtab db ':.' ; valid time delimiters
tlmtab_len equ $-tlmtab ; length of table
; date format table
dftab dw mdy ; code 0 = mon/day/year
dw dmy ; code 1 = day/mon/year
dw ymd ; code 2 = year/mon/day
dfptr dw 0 ; becomes address of
; mdy, dmy, or ymd
mdy dw n2 ; day
dw n1 ; month
dw n3 ; year
dmy dw n1 ; day
dw n2 ; month
dw n3 ; year
ymd dw n3 ; day
dw n2 ; month
dw n1 ; year
daytab dw 31,28,31 ; days in month
dw 30,31,30
dw 31,31,30
dw 31,30,31
cbuff db 34 dup (0) ; current country info
_DATA ends
_TEXT segment word public 'CODE'
assume cs:_TEXT,ds:DGROUP
extrn atoi:near ; we need ATOI routine
public scantime ; make these routines
public scandate ; available to Linker
scantime proc near ; convert ASCII time to binary
push ax ; save registers
push bx
push di
push es
call getctry ; get internationalization
; info if first call
call chknum ; convert first field
jc scant9 ; jump, bad number
mov n1,ax ; save result
mov al,[si-1] ; check time delimiter
call chktlm
jc scant9 ; jump if no good
call chknum ; convert second field
jc scant9 ; jump, bad number
mov n2,ax ; save result
mov n3,0 ; force seconds = 0
mov al,[si-1] ; another field present?
call chktlm ; if no delimiter,
jc scant1 ; assume seconds absent
call chknum ; convert third field
jc scant9 ; jump, bad number
mov n3,ax ; save value
scant1: ; validate entry
cmp word ptr n1,0 ; hours must be 0-23
jc scant9 ; jump, bad hour
cmp word ptr n1,24
cmc
jc scant9 ; jump, bad hour
cmp word ptr n2,0 ; minutes must be 0-59
jc scant9 ; jump, bad minute
cmp word ptr n2,60
cmc
jc scant9 ; jump, bad minute
cmp word ptr n3,0 ; seconds must be 0-59
jc scant9 ; jump, bad second
cmp word ptr n3,60
cmc
jc scant9 ; jump, bad second
; load the results...
mov ch,byte ptr n1 ; hours
mov cl,byte ptr n2 ; minutes
mov dh,byte ptr n3 ; seconds
mov dl,0 ; hundredths always = 0
scant9: ; common exit point
pop es ; restore registers
pop di
pop bx
pop ax
ret ; return to caller
scantime endp
scandate proc near ; convert ASCII date to binary
push ax ; save registers
push bx
push di
push es
call getctry ; get internationalization
; info if first call
call chknum ; convert first field
jc scand9 ; jump, bad number
mov n1,ax ; save result
mov al,[si-1] ; get delimiter
call chkdlm ; and check it
jc scand9 ; exit, bad delimiter
call chknum ; convert second field
jc scand9 ; jump, bad number
mov n2,ax ; save result
mov al,[si-1] ; get delimiter
call chkdlm ; and check it
jc scand9 ; exit, bad delimiter
call chknum ; convert third field
jc scand9 ; jump, bad number
mov n3,ax ; and save result
; validate entry and
; load results...
mov bx,dfptr ; point to year
mov bx,[bx+4] ; year must be 80-99
cmp word ptr [bx],80
jc scand9 ; jump, bad year
cmp word ptr [bx],100
cmc
jc scand9 ; jump, bad year
mov cx,[bx] ; load year and correct
add cx,1900 ; to range 1980-1999
; adjust days/month table
mov daytab+2,28 ; assume not leap year
test word ptr [bx],3 ; is it a leap year?
jnz scand1 ; jump, not multiple of 4
mov daytab+2,29 ; fix table for leap year
scand1: mov bx,dfptr ; point to month
mov bx,[bx+2]
cmp word ptr [bx],1 ; month must be 1-12
jc scand9 ; jump, bad month
cmp word ptr [bx],13
cmc
jc scand9 ; jump, bad month
mov dh,byte ptr [bx]; load month result
mov di,[bx] ; also prepare to index
dec di ; into days/month table
shl di,1
mov bx,dfptr ; point to day
mov bx,[bx]
cmp word ptr [bx],1 ; day must be >= 1
jc scand9 ; jump, bad day
mov ax,[di+daytab] ; get max day for this
; month from table
cmp ax,[bx]
jc scand9 ; jump, bad day
mov dl,byte ptr [bx]; load day result
scand9: ; common exit point
pop es ; restore registers
pop di
pop bx
pop ax
ret ; return to caller
scandate endp
chkdlm proc near ; check date delimiter
; call with:
; AL = character to check
; returns:
; Carry = Clear if OK
; Carry = Set if not OK
push ds ; make delimiter table
pop es ; addressable
mov di,offset DGROUP:dlmtab
mov cx,dlmtab_len
repne scasb ; compare to table
je chkd9 ; jump if match found
; (Carry is cleared)
stc ; else force Carry = set
chkd9: ret ; back to caller
chkdlm endp
chktlm proc near ; check time delimiter
; call with:
; AL = character to check
; returns:
; Carry = Clear if OK
; Carry = Set if not OK
push ds ; make delimiter table
pop es ; addressable
mov di,offset DGROUP:tlmtab
mov cx,tlmtab_len
repne scasb ; compare to table
je chkt9 ; jump if match found
; (Carry is cleared)
stc ; else force Carry = set
chkt9: ret ; back to caller
chktlm endp
chknum proc near ; check for valid numeric
; field and convert it
; call with:
; DS:DI = ASCII field
; returns:
; Carry = clear if OK
; AX = value of field
; or
; Carry = set if not OK
; check if >= '0'
cmp byte ptr [si],'0'
jb chkn1 ; jump, bad digit
; check if <= '9'
cmp byte ptr [si],'9'+1
cmc ; invert Carry flag
jc chkn1 ; jump, bad digit
call atoi ; convert field and
clc ; clear carry flag
chkn1: ret ; back to caller
chknum endp
getctry proc near ; get country information
test dfptr,-1 ; did we already get info?
jnz getc2 ; if we did, just exit
mov ax,3000h ; Fxn. 30h = get DOS vers.
int 21h ; transfer to MS-DOS
or al,al ; is it version 1.x?
jz getc1 ; yes, jump
mov ax,3800h ; get current country info
mov dx,offset DGROUP:cbuff
int 21h ; transfer to MS-DOS
getc1: ; get date code (default=0)
mov bx,word ptr cbuff
shl bx,1 ; extract pointer to
mov ax,[bx+dftab] ; date format table
mov dfptr,ax
getc2: ret ; back to caller
getctry endp
_TEXT ends
end